package com.lzh.file.store;

import com.lzh.file.config.FileSystemConfigProperties;
import com.lzh.runke.core.web_base.constant.StringConstant;
import com.lzh.runke.core.web_base.helper.UUIDHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 文件系统存储实现
 *
 * @author xie
 */
@Slf4j
@Component("FileStoreFileSystem")
public class FileStoreFileSystem implements FileStoreApi {

    private final String path;

    public FileStoreFileSystem(FileSystemConfigProperties configProperties) {
        this.path = StringUtils.appendIfMissing(configProperties.getPath(), File.separator);
    }

    /**
     * 保存文件
     *
     * @param file 文件
     * @return filename 自动生成的UUID文件名
     */
    @Override
    public String save(File file) {
        Assert.notNull(file, "参数file不能为空");
        try {
            String extension = FilenameUtils.getExtension(file.getName());
            return this.save(new FileInputStream(file), extension);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 保存文件
     *
     * @param file 文件
     * @return filename 自动生成的UUID文件名
     */
    @Override
    public String save(MultipartFile file) {
        Assert.notNull(file, "参数file不能为空");
        try {
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            return this.save(file.getInputStream(), extension);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 保存文件
     *
     * @param stream    文件流
     * @param extension 文件扩展名
     * @see com.lzh.file.constant.FileConstant .FILE_EXTENSION_*
     */
    @Override
    public String save(InputStream stream, String extension) {
        Assert.notNull(stream, "参数stream不能为空");
        Assert.notNull(extension, "参数extension不能为空");

        // 生成UUID文件名 无后缀
        StringBuilder filename = new StringBuilder(UUIDHelper.randomUUID());
        // 生成文件目录
        StringBuilder fullPathBuilder = buildFullPath(filename.toString());

        // 创建文件目录
        File dir = new File(fullPathBuilder.toString());
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                throw new RuntimeException("创建目录失败");
            }
        }

        // 生成完整文件名
        filename.append(StringConstant.DOT).append(extension);

        // 保存文件
        File fileSaved = new File(dir, filename.toString());

        try {
            FileUtils.copyInputStreamToFile(stream, fileSaved);
            return filename.toString();
        } catch (IllegalStateException | IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据文件名 删除已上传文件
     *
     * @param filename
     * @return
     */
    @Override
    public boolean deleteFile(String filename) {
        Assert.notNull(filename, "参数filename不能为空");

        File file = new File(buildFullPath(filename).toString(), filename);
        return revertFile(file);
    }

    @Override
    public boolean deleteFile(String[] filenames) {
        for (String filename : filenames) {
            File file = new File(buildFullPath(filename).toString(), filename);
            boolean deleted = revertFile(file);
            if (!deleted) {
                log.error("删除文件失败: filename={}", filename);
            }
        }
        return true;
    }

    /**
     * 文件下载
     *
     * @param filename 保存文件名
     * @return
     * @throws IOException
     */
    @Override
    public byte[] loadFileBytes(String filename) {
        Assert.notNull(filename, "参数filename不能为空");
        File file = this.loadFile(filename);
        try {
            return FileUtils.readFileToByteArray(file);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public File loadFile(String filename) {
        return new File(buildFullPath(filename).append(File.separator).append(filename).toString());
    }

    /**
     * 根据uuid文件名分目录
     *
     * @param uuidName
     */
    @Override
    public StringBuilder buildFullPath(String uuidName) {
        Assert.hasText(uuidName, "参数uuidName不能为空");

        StringBuilder pathBuilder = new StringBuilder(this.path);

        return pathBuilder.append(uuidName.substring(0, 2).toLowerCase())
                .append(File.separator).append(uuidName.substring(2, 4).toLowerCase())
                .append(File.separator).append(uuidName.substring(4, 6).toLowerCase())
                .append(File.separator).append(uuidName.substring(6, 8).toLowerCase());

    }

    /**
     * 根据文件 删除已上传文件
     *
     * @param file
     * @return
     */
    private boolean revertFile(File file) {
        Assert.notNull(file, "参数file不能为空");
        return file.delete();
    }
}
